package com.base.cn.platform.os.common.interceptor.keyword;

import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.xss.XssHttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;

public class KeyWebHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    HttpServletRequest orgRequest;
    //参数内容
    private String body;
    //过滤工具
    private SensitiveFilterService filter;
    //敏感词对象
    private Set<String> wordSet;

    public KeyWebHttpServletRequestWrapper(HttpServletRequest request,SensitiveFilterService filter,StringBuilder keyWordContext) {
        super(request);
        orgRequest = request;
        this.filter = filter;
        if(keyWordContext!=null && keyWordContext.length() > 0){
            wordSet = new HashSet<>();
            Arrays.asList(keyWordContext.toString().replaceAll("\r","|").replaceAll("\t","|").replaceAll("\n","|").replaceAll("、","|").replaceAll("/","|").replaceAll(" ","|").split("\\|")).forEach(key->{
                if(!key.trim().equals("")){
                    wordSet.add(key);
                }
            });
            this.filter.initWordSet(wordSet);
        }
        try {
            byte[] _body = StreamUtils.copyToByteArray(request.getInputStream());
            body = new String(_body, "UTF-8");
        } catch (IOException e) {
            logger.error("--------get request body error:",e);
        }
    }

    /**
     * 覆盖getParameter方法，将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值，则通过super.getParameterValues(name)来获取<br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(keyWordEncode(name));
        if (null != value) {
            value = keyWordEncode(value);
        }
        return value;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(keyWordEncode(name));
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = keyWordEncode(values[i]);
        }
        return encodedValues;
    }

    @Override
    public Map getParameterMap() {
        Map<String,String[]> paramMap = new HashMap<>();
        for (Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String[] values = (String[]) entry.getValue();
            for (int i = 0; i < values.length; i++) {
                if (values[i] instanceof String) {
                    values[i] = keyWordEncode(values[i]);
                }
            }
            entry.setValue(values);
        }
        return paramMap;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        ServletInputStream inputStream = null;
        if (StringUtils.isNotEmpty(body)) {
            body = keyWordEncode(body);
            final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes("utf-8"));
            inputStream = new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
                @Override
                public boolean isFinished() {
                    return false;
                }
                @Override
                public boolean isReady() {
                    return true;
                }
                @Override
                public void setReadListener(ReadListener listener) {
                }
            };
        }
        return inputStream;
    }

    /**
     * 覆盖getHeader方法，将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值，则通过super.getHeaders(name)来获取<br/>
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(keyWordEncode(name));
        if (value != null) {
            value = keyWordEncode(value);
        }
        return value;
    }

    /**
     * 执行过滤敏感词
     *
     * @param paramsVal 参数数据
     * @return 返回过滤后的数据
     */
    private String keyWordEncode(String paramsVal) {
        if (paramsVal == null || paramsVal.isEmpty()) {
            return paramsVal;
        }
        if(wordSet==null || ObjectUtils.isEmpty(wordSet)){
            return paramsVal;
        }
        return filter.replaceSensitiveWord(paramsVal, 1, "*");
    }
    /**
     * 获取最原始的request
     *
     * @return
     */
    public HttpServletRequest getOrgRequest() {
        return orgRequest;
    }

    /**
     * 获取最原始的request的静态方法
     *
     * @return
     */
    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
        if (req instanceof XssHttpServletRequestWrapper) {
            return ((XssHttpServletRequestWrapper) req).getOrgRequest();
        }
        return req;
    }
}
